package org.example.controller;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.example.entity.UserDealerImportForm;
import org.example.handler.DealerImportVerifyHandler;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 望轩
 * @createDate 2025/5/19 15:01
 *
 */
@RestController
@Slf4j
public class ExcelController {
    @Resource
    private DealerImportVerifyHandler dealerImportVerifyHandler;

    //导入excel文件的时候，肯定会对导入的文件的excel内容进行校验。比如如果导入的excel文件的列有一列的名字是level，这一列不能为空，那么
    //我们该如何进行校验呢？方法很简单，使用validation进行校验即可，我们可以通过@NotBlank注解进行校验。可以参照这里的UserDealerImportForm类。
    // 但是假如我们还要求这个level的值还只能是1或者2呢？这个时候再使用validation的注解肯定不能满足了，那么这个时候我们就要使用excel自带的Handler处理器
    //处理器详情可以参照上面的DealerImportVerifyHandler。
    //最终错误的行的错误数据会返回到failList集合里，正确的行的正确的数据会返回到list集合里
    //那么既然校验excel文件异常，一部分使用的是validation注解，一部分使用的是excle处理器，那么假如都有异常，两部分异常信息的展示顺序是怎么样的呢？
    //会先展示validation注解校验的异常，然后再展示excel处理器校验的异常，如下：["第3行的错误原因：联系人邮件格式不正确,客户类型格式错误，只能为1或2"]
    //上卖弄的联系人邮件格式不正确就是validation处理的异常
    @PostMapping("/excelImport")
    public String excelImport(@RequestParam("file") MultipartFile file, HttpServletResponse response) throws Exception {
        if (file.isEmpty()) {
            return "上传文件不能为空";
        }

        // 获取上传文件输入流
        InputStream inputStream;
        try {
            inputStream = file.getInputStream();
        } catch (Exception e) {
            log.error("获取上传文件流失败,详情如下:", e);
            throw new Exception("获取上传文件流失败");
        }

        //开启Excel导入校验
        ImportParams importParams = new ImportParams();
        importParams.setNeedVerify(true);
        importParams.setVerifyHandler(dealerImportVerifyHandler);

        //读取Excel数据
        ExcelImportResult<UserDealerImportForm> result = ExcelImportUtil.importExcelMore(inputStream, UserDealerImportForm.class, importParams);
        if (CollectionUtils.isEmpty(result.getFailList()) && CollectionUtils.isEmpty(result.getList())) {
            return "未检查到有效数据，请按照模板格式上传";
        }

        List<UserDealerImportForm> failList = result.getFailList();
        List<String> errorMsgList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(failList)) {
            for (UserDealerImportForm entity : failList) {
                int line = entity.getRowNum() + 1;
                String msg = "第" + line + "行的错误原因：" + entity.getErrorMsg();
                errorMsgList.add(msg);
            }
        }

        //如果错误集合不只是一个元素，也就是说不只是只有一行填写的内容有问题，那么我们需要把所有行的问题都返回，一共业务方参考，他们看到这些值可以一次性的修改所有异常
        //最终结果如下：["第2行的错误原因：签约开始时间只能是aaa","第3行的错误原因：客户类型格式错误，只能为1或2"]
        if (CollectionUtils.isNotEmpty(errorMsgList)) {
            return JSONObject.toJSONString(errorMsgList);
        }

        //这个是导入的excel文件中校验通过的所有的行，只有在excel表中没有数据异常的时候我们才会去解析正常的行，去存入到数据库
        //如果excel本身就有异常数据，那么我们直接就把异常数据返回给用户即可，不用再把正常数据行入库了，让用户修改完数据之后再入库
        List<UserDealerImportForm> successList = result.getList();

        return "成功";

    }
}
